What is C-level extensibility?

The C-level extensibility mechanism lets you implement Dreamweaver extensibility files using a combination of JavaScript and your own C code. You define functions using C, bundle them in a DLL or shared library, save the library in the Configuration/JSExtensions folder within the Dreamweaver application folder, and then call the functions from JavaScript using the JavaScript interpreter that is built into Dreamweaver.

For example, you may want to define a Dreamweaver object that inserts the contents of a user-specified file into the current document. Because client-side JavaScript does not provide any support for file I/O, you must write a function in C to provide this functionality.

You could use the following HTML and JavaScript to create a simple Insert Text from File object. Notice that the objectTag() function calls a C function named readContentsOfFile(), which is stored in a library named myLibrary.

<HTML><HEAD><SCRIPT>function objectTag() {
  fileName = document.forms[0].myFile.value;
  return myLibrary.readContentsOfFile(fileName);
}
</SCRIPT></HEAD>
<BODY><FORM>Enter the name of the file to be inserted:
<INPUT TYPE="file" NAME="myFile"></FORM></BODY></HTML>

The readContentsOfFile() function accepts a list of arguments from the user, unpacks the argument containing the file name, reads the contents of the file, and packages the contents of the file as the return value. For more information about the JavaScript data structures and functions that appear in readContentsOfFile(), see The C-level extensibility API.

JSBool
readContentsOfFile(JSContext *cx, JSObject *obj, unsigned int argc, jsval *argv, jsval *rval)
{
  char *fileName, *fileContents;
  JSBool success;
  unsigned int length;

  /* Make sure caller passed in exactly one argument. If not,
   * then tell the interpreter to abort script execution. */
  if (argc != 1){
    JS_ReportError(cx, "Wrong number of arguments", 0);
    return JS_FALSE;
  }

  /* Convert the argument to a string */
  fileName = JS_ValueToString(cx, argv[0], &length); 
  if (fileName == NULL){
    JS_ReportError(cx, "The argument must be a string", 0);
    return JS_FALSE; 
  }

  /* Use the string (the file name) to open and read a file */
  fileContents = exerciseLeftToTheReader(fileName);

  /* Store file contents in rval, which is the return value passed
   * back to the caller */
  success = JS_StringToValue(cx, fileContents, 0, *rval);
  free(fileContents);

  /* Return true to continue or false to abort the script */
  return success;
}

To ensure that the readContentsOfFile() function executes as designed rather than causing a JavaScript error, you must register the function with the JavaScript interpreter by including a function called MM_Init() in your library. When Dreamweaver loads the library at startup, it calls the MM_Init() function to get three pieces of information:

The JavaScript name of the function
A pointer to the function
The number of arguments that the function expects

The MM_Init() function for myLibrary might look like this:

void
MM_Init()
{
  JS_DefineFunction("readContentsOfFile", readContentsOfFile, 1);
}

Your library must include exactly one instance of the following macro:

/* MM_STATE is a macro that expands to some definitions that are
 * needed to interact with Dreamweaver. This macro must
 * be defined exactly once in your library. */
MM_STATE

Note: The library can be implemented in either C or C++, but the file containing MM_Init() and MM_STATE must be implemented in C. The C++ compiler garbles function names, making it impossible for Dreamweaver to find the MM_Init() function.